import { h, reactive, Ref, ref, shallowReactive } from 'vue';
import {
  IPSDEFormButton,
  IPSDEFormDetail,
  IPSDEFormDRUIPart,
  IPSDEFormGroupPanel,
  IPSDEFormItem,
  IPSDEFormPage,
  IPSEditor,
} from '@ibiz/dynamic-model-api';
import {
  LogUtil,
  Util,
  AppMobFormProps,
  MobFormCtrlController,
  IMobFormCtrlController,
  IEditorEventParam,
  AppCtrlProps,
} from 'ibz-core';
import { GenerateComponent } from '../../component-base';
import { CtrlComponentBase } from '../ctrl-component-base';
import { AppAnchorComponent, AppFormItemComponent } from '../../../components';
import {
  AppFormButtonComponent,
  AppFormDruipartComponent,
  AppFormGroupComponent,
  AppFormPageComponent,
} from '../app-mob-form';

/**
 * 移动端表单
 *
 * @author chitanda
 * @date 2021-08-06 10:08:39
 * @export
 * @class AppMobForm
 * @extends {ComponentBase}
 */
export class AppMobForm<Props extends AppCtrlProps> extends CtrlComponentBase<AppMobFormProps> {
  /**
   * @description 部件控制器
   * @protected
   * @type {IMobFormCtrlController}
   * @memberof AppMobForm
   */
  protected c!: IMobFormCtrlController;

  /**
   * @description 当前页
   * @type {Ref<string>}
   * @memberof AppMobForm
   */
  public currentPage: Ref<string> = ref('');

  /**
   * @description 设置响应式
   * @memberof AppMobForm
   */
  setup() {
    this.c = shallowReactive<MobFormCtrlController>(this.getCtrlControllerByType('FORM') as MobFormCtrlController);
    super.setup();
  }

  /**
   * @description 初始化响应式属性
   * @memberof AppMobForm
   */
  public initReactive() {
    super.initReactive();
    this.c.data = reactive(this.c.data);
    this.c.detailsModel = reactive(this.c.detailsModel);
    this.c.errorMessages = reactive(this.c.errorMessages);
  }

  /**
   * @description 表单分页点击事件
   * @returns
   * @memberof AppMobForm
   */
  public segmentChanged(e: any) {
    if (e && e.detail && e.detail.value) {
      this.currentPage.value = e.detail.value;
    }
  }

  /**
   * @description 获取栅格布局
   * @param parent 容器
   * @param child 子成员
   * @memberof AppMobForm
   */
  public getGridLayoutProps(parent: any, child: any) {
    const layout = parent?.getPSLayout?.()?.layout;
    let { colXS, colSM, colMD, colLG, colXSOffset, colSMOffset, colMDOffset, colLGOffset } = child?.getPSLayoutPos?.();
    // 设置初始值
    colXS = !colXS || colXS == -1 ? 12 : colXS / 2;
    colSM = !colSM || colSM == -1 ? 12 : colSM / 2;
    colMD = !colMD || colMD == -1 ? 12 : colMD / 2;
    colLG = !colLG || colLG == -1 ? 12 : colLG / 2;
    colXSOffset = !colXSOffset || colXSOffset == -1 ? 0 : colXSOffset / 2;
    colSMOffset = !colSMOffset || colSMOffset == -1 ? 0 : colSMOffset / 2;
    colMDOffset = !colMDOffset || colMDOffset == -1 ? 0 : colMDOffset / 2;
    colLGOffset = !colLGOffset || colLGOffset == -1 ? 0 : colLGOffset / 2;
    if (layout == 'TABLE_12COL') {
      // 重新计算12列的栅格数值
      colXS = Math.min(colXS * 2, 12);
      colSM = Math.min(colSM * 2, 12);
      colMD = Math.min(colMD * 2, 12);
      colLG = Math.min(colXS * 2, 12);
      // 重新计算12列的栅格偏移
      const sign = (num: number) => (num == 0 ? 0 : num / Math.abs(num));
      colXSOffset = sign(colXSOffset) * Math.min(colXSOffset * 2, 12);
      colSMOffset = sign(colSMOffset) * Math.min(colSMOffset * 2, 12);
      colMDOffset = sign(colMDOffset) * Math.min(colMDOffset * 2, 12);
      colLGOffset = sign(colLGOffset) * Math.min(colLGOffset * 2, 12);
    }
    return {
      'size-lg': colLG,
      'size-md': colMD,
      'size-sm': colSM,
      'size-xs': colXS,
      'offset-lg': colLGOffset,
      'offset-md': colMDOffset,
      'offset-sm': colSMOffset,
      'offset-xs': colXSOffset,
    };
  }

  /**
   * @description 获取栅格布局样式
   * @param item 表单成员
   * @memberof AppMobForm
   */
  public getGridLayoutStyle(item: IPSDEFormDetail) {
    const { name, width, height } = item;
    const style: any = {};
    if (!this.c.detailsModel[name]?.visible) {
      Object.assign(style, { display: 'none' });
    }
    if (width && width > 0) {
      Object.assign(style, { width: `${width}px` });
    }
    if (height && height > 0) {
      Object.assign(style, { height: `${height}px` });
    }
    return style;
  }

  /**
   * @description 获取flex布局样式
   * @param item 表单成员
   * @memberof AppMobForm
   */
  public getFlexLayoutStyle(item: IPSDEFormDetail) {
    const layoutPos = item.getPSLayoutPos();
    const style: any = {};
    if (!this.c.detailsModel[item.name]?.visible) {
      Object.assign(style, { display: 'none' });
    }
    if (layoutPos) {
      const { height, width } = layoutPos;
      //  宽高
      if (width) {
        Object.assign(style, { width: `${width}px` });
      }
      if (height) {
        Object.assign(style, { height: `${height}px` });
      }
    }
    return style;
  }

  /**
   * @description 渲染锚点
   * @return {*}
   * @memberof AppMobForm
   */
  public renderAnchor() {
    const scrollContainerTag = `${Util.srfFilePath2(
      (this.c.controlInstance as any)?.getParentPSModelObject?.()?.codeName,
    )} .view-body`;
    return h(AppAnchorComponent, {
      anchors: this.c.groupAnchors,
      scrollContainerTag: scrollContainerTag,
    });
  }

  /**
   * @description 根据detailType绘制对应detail
   * @param {*} modelJson 模型数据
   * @param {number} index 下标
   * @memberof AppMobForm
   */
  public renderByDetailType(modelJson: any, index: number) {
    if (modelJson.getPSSysPFPlugin()?.pluginCode) {
      const ctrlItemPluginInstance = App.getPluginService().getCtrlItemPluginByTag(
        modelJson.getPSSysPFPlugin()?.pluginCode,
      );
      if (ctrlItemPluginInstance) {
        return ctrlItemPluginInstance.renderItem(this.c.data[modelJson.name], this.c, this);
      }
    } else {
      switch (modelJson.detailType) {
        case 'FORMPAGE':
          return this.renderFormPage(modelJson as IPSDEFormPage, index);
        case 'GROUPPANEL':
          return this.renderGroupPanel(modelJson as IPSDEFormGroupPanel, index);
        case 'FORMITEM':
          return this.renderFormItem(modelJson as IPSDEFormItem, index);
        case 'DRUIPART':
          return this.renderDruipart(modelJson as IPSDEFormDRUIPart, index);
        case 'BUTTON':
          return this.renderButton(modelJson as IPSDEFormButton, index);
        default:
          LogUtil.log(`暂未实现 ${modelJson.detailType} 类型表单成员`);
      }
    }
  }

  /**
   * @description 绘制子表单成员,布局控制
   * @param {*} modelJson 表单成员模型
   * @returns {*}
   * @memberof AppMobForm
   */
  public renderDetails(modelJson: any): any {
    const formDetails: IPSDEFormDetail[] = modelJson.getPSDEFormDetails();
    const layout: any = modelJson.getPSLayout();
    // 没有子表单成员
    if (!formDetails || formDetails.length == 0) {
      return null;
    }
    // flex布局
    if (layout && layout.layout == 'FLEX') {
      let cssStyle: string = 'width: 100%; height: 100%; overflow: auto; display: flex;';
      cssStyle += layout.dir ? `flex-direction: ${layout.dir};` : '';
      cssStyle += layout.align ? `justify-content: ${layout.align};` : '';
      cssStyle += layout.vAlign ? `align-items: ${layout.vAlign};` : '';
      return (
        <div style={cssStyle}>
          {formDetails.map((item: IPSDEFormDetail, index: number) => {
            const detailStyle = this.getFlexLayoutStyle(item);
            return <div style={detailStyle}>{this.renderByDetailType(item, index)}</div>;
          })}
        </div>
      );
    } else {
      // 栅格布局
      return (
        <ion-row style='height: 100%;'>
          {formDetails.map((item: IPSDEFormDetail, index: number) => {
            if (!(item as any).hidden) {
              const attrs = this.getGridLayoutProps(modelJson, item);
              const detailStyle = this.getGridLayoutStyle(item);
              return (
                <ion-col class={`${this.c.controlInstance.name}-layout-container`} style={detailStyle} {...attrs}>
                  {this.renderByDetailType(item, index)}
                </ion-col>
              );
            }
          })}
        </ion-row>
      );
    }
  }

  /**
   * @description 绘制编辑器
   * @returns {*}
   * @memberof AppMobForm
   */
  public renderEditor(editor: IPSEditor, parentItem: any): any {
    const targetCtrlComponent: any = App.getComponentService().getEditorComponent(
      editor?.editorType,
      editor?.editorStyle ? editor?.editorStyle : 'DEFAULT',
      editor.getPSSysPFPlugin() ? `${editor?.editorType}_${editor?.editorStyle}` : undefined,
      this.c.detailsModel[editor.name]?.infoMode,
    );
    return h(targetCtrlComponent, {
      editorInstance: editor,
      containerCtrl: this.c.controlInstance,
      parentItem: parentItem,
      contextData: this.c.data,
      contextState: this.c.formState,
      ctrlService: this.c.ctrlService,
      navContext: Util.deepCopy(this.c.context),
      navParam: Util.deepCopy(this.c.viewParam),
      disabled: this.c.detailsModel[editor.name]?.disabled,
      value: this.c.data[editor?.name || ''],
      modelService: this.c.modelService,
      onEditorEvent: (event: IEditorEventParam) => {
        this.c.handleEditorEvent(event);
      },
    });
  }

  /**
   * @description 绘制表单项
   * @returns {*}
   * @memberof AppMobForm
   */
  public renderFormItem(modelJson: IPSDEFormItem, index: number): any {
    const editor = modelJson.getPSEditor();
    return h(
      AppFormItemComponent,
      {
        formState: this.c.formState,
        parameterName: this.c.appDeCodeName,
        navContext: Util.deepCopy(this.c.context),
        navParam: Util.deepCopy(this.c.viewParam),
        viewCtx: this.c.viewCtx,
        data: this.c.data,
        name: this.c.controlInstance.name,
        modelService: this.c.modelService,
        ignorefieldvaluechange: this.c.ignorefieldvaluechange,
        c: this.c.detailsModel[modelJson.name],
      },
      () => {
        return editor ? this.renderEditor(editor, modelJson) : null;
      },
    );
  }

  /**
   * @description 绘制关系界面
   * @returns {*}
   * @memberof AppFormBase
   */
  public renderDruipart(modelJson: IPSDEFormDRUIPart, index: number): any {
    const appDataEntity = this.c.controlInstance.getPSAppDataEntity();
    return h(AppFormDruipartComponent, {
      formState: this.c.formState,
      parameterName: appDataEntity?.codeName,
      navContext: Util.deepCopy(this.c.context),
      navParam: Util.deepCopy(this.c.viewParam),
      viewCtx: this.c.viewCtx,
      data: this.c.data,
      name: this.c.controlInstance.name,
      modelService: this.c.modelService,
      ignorefieldvaluechange: this.c.ignorefieldvaluechange,
      c: this.c.detailsModel[modelJson.name],
    });
  }

  /**
   * @description 绘制按钮
   * @returns {*}
   * @memberof AppMobForm
   */
  public renderButton(modelJson: IPSDEFormButton, index: number): any {
    return h(AppFormButtonComponent, {
      formState: this.c.formState,
      parameterName: this.c.appDeCodeName,
      navContext: Util.deepCopy(this.c.context),
      navParam: Util.deepCopy(this.c.viewParam),
      viewCtx: this.c.viewCtx,
      data: this.c.data,
      name: this.c.controlInstance.name,
      modelService: this.c.modelService,
      ignorefieldvaluechange: this.c.ignorefieldvaluechange,
      c: this.c.detailsModel[modelJson.name],
    });
  }

  /**
   * @description 绘制分组面板
   * @returns {*}
   * @memberof AppMobForm
   */
  public renderGroupPanel(modelJson: IPSDEFormGroupPanel, index: number): any {
    return h(
      AppFormGroupComponent,
      {
        formState: this.c.formState,
        parameterName: this.c.appDeCodeName,
        navContext: Util.deepCopy(this.c.context),
        navParam: Util.deepCopy(this.c.viewParam),
        viewCtx: this.c.viewCtx,
        data: this.c.data,
        name: this.c.controlInstance.name,
        modelService: this.c.modelService,
        ignorefieldvaluechange: this.c.ignorefieldvaluechange,
        c: this.c.detailsModel[modelJson.name],
      },
      () => {
        return this.renderDetails(modelJson);
      },
    );
  }

  /**
   * @description 绘制表单分页
   * @returns {*}
   * @memberof AppMobForm
   */
  public renderFormPage(modelJson: IPSDEFormPage, index: number): any {
    return h(
      AppFormPageComponent,
      {
        formState: this.c.formState,
        parameterName: this.c.appDeCodeName,
        navContext: Util.deepCopy(this.c.context),
        navParam: Util.deepCopy(this.c.viewParam),
        viewCtx: this.c.viewCtx,
        data: this.c.data,
        name: this.c.controlInstance.name,
        currentPage: this.currentPage.value,
        ignorefieldvaluechange: this.c.ignorefieldvaluechange,
        c: this.c.detailsModel[modelJson.name],
      },
      () => {
        return this.renderDetails(modelJson);
      },
    );
  }

  /**
   * @description 绘制表单内容
   * @returns {*}
   * @memberof AppMobForm
   */
  public renderFormContent() {
    const { noTabHeader } = this.c.controlInstance;
    const formPages = this.c.controlInstance.getPSDEFormPages();
    if (!this.currentPage.value && formPages) {
      this.currentPage.value = formPages[0].codeName;
    }
    if (formPages && formPages.length > 0) {
      if (noTabHeader) {
        return formPages.map((item: IPSDEFormPage, index: number) => {
          return this.renderFormPage(item, index);
        });
      } else {
        const controlName = this.c.controlInstance.name;
        return (
          <div class={`${controlName}-container`}>
            <div class={`${controlName}-header`}>
              <ion-segment value={this.currentPage.value} onIonChange={($event: any) => this.segmentChanged($event)}>
                {formPages.map((item: IPSDEFormPage, index: number) => {
                  // 表单分页标题样式
                  const pageClass = item.getLabelPSSysCss()?.cssName;
                  return (
                    <ion-segment-button value={item.codeName} class={pageClass}>
                      <ion-label>
                        {item.getPSSysImage() && <app-icon icon={item.getPSSysImage()}></app-icon>}
                        {this.$tl(item?.getCapPSLanguageRes()?.lanResTag, item.caption)}
                      </ion-label>
                    </ion-segment-button>
                  );
                })}
              </ion-segment>
            </div>
            <div class={`${controlName}-body`}>
              {formPages.map((item: IPSDEFormPage, index: number) => {
                return this.renderFormPage(item, index);
              })}
            </div>
          </div>
        );
      }
    }
  }

  /**
   * @description 部件样式名
   * @readonly
   * @type {any}
   * @memberof AppMobForm
   */
  get classNames(): any {
    const { name, codeName } = this.c.controlInstance;
    const classNames: any = {
      'container-margin': true,
      'container-padding': true,
      'app-ctrl': true,
      [name]: true,
      [Util.srfFilePath2(codeName)]: true,
    };
    const sysCss = this.c.controlInstance.getPSSysCss?.();
    if (sysCss) {
      Object.assign(classNames, { [sysCss.cssName]: true });
    }
    return classNames;
  }

  /**
   * @description 绘制移动端表单
   * @returns {JSX.Element | JSX.Element[] | null}
   * @memberof AppMobForm
   */
  render(): JSX.Element | JSX.Element[] | null {
    if (!this.controlIsLoaded.value) {
      return null;
    }
    const controlStyle = {
      width: this.c.controlInstance.width
        ? `${this.c.controlInstance.width}px`
        : this.c.controlInstance.formWidth
        ? `${this.c.controlInstance.formWidth}`
        : '',
      height: this.c.controlInstance.height ? `${this.c.controlInstance.height}px` : '',
    };
    return (
      <div class={{ ...this.classNames }} style={controlStyle}>
        {this.c.groupAnchors.length ? this.renderAnchor() : null}
        {this.renderPullDownRefresh()}
        {this.renderFormContent()}
      </div>
    );
  }
}

// 移动端表单部件
export const AppMobFormComponent = GenerateComponent(AppMobForm, Object.keys(new AppMobFormProps()));
